package RMIServer;

import java.io.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

import Middleware.IPlayer;
import Middleware.IRoom;
import Middleware.IServer;

public class Server extends UnicastRemoteObject implements IServer {
	private static final long serialVersionUID = 8123748828955256369L;
	
	private HashMap<String,IRoom> roomList;
	private ArrayList<IPlayer> playerList;
	private ArrayList<User> userList;
	private String userInfoPath;
	private int decksToUse=3;
	
	public Server() throws RemoteException
	{
		userInfoPath="users.dat";
		config();
		roomList = new HashMap<String,IRoom>();
		playerList = new ArrayList<IPlayer>();

//		userList = read(userInfoPath);

		userList = new ArrayList<User>();
		User u;
		u = new User("alex", "alex", "Alex", 1);
		u.addCredit(10000);
		this.registerUser(u);
		u = new User("andi", "andi", "Andi", 2);
		u.addCredit(10000);
		this.registerUser(u);
		u = new User("casian", "casian", "Casian", 3);
		u.addCredit(10000);
		this.registerUser(u);
		u = new User("dan", "dan", "Dan", 4);
		u.addCredit(10000);
		this.registerUser(u);
		save();
	}
	
	private void config()
	{
		try	{
			FileInputStream fis = new FileInputStream("config.ini");
			Scanner sc = new Scanner(fis);
			userInfoPath = sc.nextLine();
			sc.close();
			fis.close();
		} catch(IOException e) {
			System.out.println("Exception in reading config file: " + e);
			e.printStackTrace();
		}
	}
	
	public boolean authenticate(IPlayer user) throws RemoteException {
		for(IPlayer p : playerList) {
			if(p.getUsername().equals(user.getUsername())) {
				return true;
			}
		}
		return false;
	}
	
	public IPlayer getPlayer(String username, String password) {
		boolean found = false;
		for (User u : userList) {
			if(u.isThisYou(username, password))
			{
				found = true;
			}
		}
		
		if(found == false) {
			return null;
		}
		
		for(IPlayer p : playerList) {
			if(p.getUsername().equals(username)) {
				return p;
			}
		}
		return null;
	}
	
	public boolean registerUser(User u)
	{
		return userList.add(u);
	}
	
	@SuppressWarnings("unchecked")
	public <T> ArrayList<T> read(String path) throws RemoteException
	{
		ArrayList<T> list = new ArrayList<T>();
		ObjectInputStream ois = null;
		try {
			FileInputStream fis = new FileInputStream(path);
			ois = new ObjectInputStream(fis);
			list = (ArrayList<T>)ois.readObject();					
		} catch (IOException e) {
			System.out.println("Exception in read: " + e);
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			System.out.println("Exception in read: " + e);
			e.printStackTrace();
		} finally {
			try {
				if (ois != null) {
					ois.close();
				}
			} catch (IOException e) {
				System.out.println("Exception in read: " + e);
				e.printStackTrace();
			}
		}
		
		return list;
	}
	
	@SuppressWarnings("unchecked")
	private void save(String path, ArrayList list) {
		ObjectOutputStream oos = null;
		try {
			FileOutputStream fos = new FileOutputStream(path);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(list);
		} catch(IOException e) {
			System.out.println("Exception in save: " + e);
			e.printStackTrace();
		} finally {
			try {
				if (oos != null) {
					oos.close();
				}
			} catch (IOException e) {
				System.out.println("Exception in save: " + e);
				e.printStackTrace();
			}
		}
	}
	
	public void save() 
	{
		save(userInfoPath, userList);	
	}
	
	@Override
	public IRoom getRoom(String owner) throws RemoteException
	{
		if(roomList.containsKey(owner))
		{
			if(roomList.get(owner).hasRoom())
			{
				return roomList.get(owner);
			}
		}
		return null;
	}
	
	@Override
	public IRoom createRoom(IPlayer user,int maxPlayers) throws RemoteException {
		System.out.println("createRoom1");
		if(authenticate(user))
		{
			System.out.println("createRoom2");
			IRoom r = new Room(maxPlayers,decksToUse,this,"room-"+user.getUsername());
			roomList.put("room-"+user.getUsername(),r);
			System.out.println("chiar am facut room : " + r.getRMIName());
			return r;
		}
		else return null;
	}
	
	public void removeRoom(IRoom room) {
		try {
			System.out.println("BEFORE: ");
			for(IRoom r : roomList.values()) {
				System.out.println(r.getRMIName());
			}
			for(String s : roomList.keySet()) {
				System.out.println(s);
				if(s.equals(room.getRMIName())) {
					System.out.println("AM GASIT");
					roomList.remove(s);
				}
			}
			System.out.println("AFTER: ");
			for(IRoom r : roomList.values()) {
				System.out.println(r.getRMIName());
			}
		} catch(Exception e) {
			System.out.println("Exception: " +e.getMessage());
		}
	}
	
	public boolean bet(String username,int amount) throws RemoteException
	{
		for(User u:userList)
		{
			if(u.username().equals(username))
				if(amount<=u.interogateCredit())
				{
					u.withdrawCredit(amount);
					return true;
				}
				else return false;
		}
		return false;
	}
	@Override
	public IPlayer requestLogin(String username, String password)
			throws RemoteException {
		for (User u : userList) {
			if(u.isThisYou(username, password))
			{
				IPlayer player = new Player(u);
				if(!authenticate(player))
					playerList.add(player);
				return player;
			}
		}
		return null;
	}

	@Override
	public void requestLogout(IPlayer user) throws RemoteException {
		if(authenticate(user))
		{
			playerList.remove(user);
		}
	}

	@Override
	public void addWinnings(String username, double amount) throws RemoteException {
		for(User u:userList)
		{
			if(u.username().equals(username))
				u.addCredit(amount);
		}
	}

	public ArrayList<String> getRoomNames() throws RemoteException {
		ArrayList<String> rooms = new ArrayList<String>(this.roomList.size());
		for(String room : roomList.keySet()) {
			rooms.add(room);
		}
		return rooms;
	}
	public IRoom[] getRooms() throws RemoteException {
		IRoom[] rooms = new IRoom[this.roomList.size()];
		int i=0;
		
		for(IRoom room : roomList.values()) {
			rooms[i++] = room;
		}
		return rooms;
	}
	@Override
	public IRoom getRoomByKey(String key) throws RemoteException {
		return roomList.get(key);
	}
}
